require('./util/util')
const config = require('./util/config')

if (process.argv.length == 2) {
    config.domain = 'zoro.site'
}

const logger = require('log4js').getLogger(),
    http = require('http'), //require('http2'),
    https = require('https'),
    url = require('url'),
    fs = require('fs'),
    path = require('path'),
    mysql = require('mysql'),
    // WebSocketServer = require('ws').Server,
    ffmpeg = require('fluent-ffmpeg'),
    sessionMng = require('./mng/sessionMng'),
    htmlDao = require('./dao/htmlDao'),
    svc = { // short for service
        search: {
            serve: require('./service/searchService')
        },
        visit: {
            serve: require('./service/visitService')
        },
        add: {
            serve: require('./service/addService'),
            needLogin: true
        },
        login: {
            serve: require('./service/loginService')
        },
        getUrlInfo: {
            serve: require('./service/getUrlInfoService'),
            needLogin: true
        },
        updateUrlInfo: {
            serve: require('./service/updateUrlInfoService'),
            needLogin: true
        },
        //getStarUrl: {
        //	serve: require('./service/getStarUrlService')
        //},
        updateHtml: {
            serve: require('./service/updateHtmlService'),
            needLogin: true
        },
        getPossibleWords: {
            serve: require('./service/getPossibleWordsService')
        },
        //addShoppingItem: {
        //	serve: require('./service/addShoppingItemService'),
        //	needLogin: true
        //},
        getLoginStatus: {
            serve: require('./service/getLoginStatusService')
        },
        //getUploadPercentage: {
        //	serve: require('./service/getUploadPercentageService'),
        //	needLogin: true
        //},
        //uploadPhoto: {
        //	serve: require('./service/uploadPhotoService'),
        //	needLogin: true,
        //	allowUsers: [2]
        //},
        //getPhoto: {
        //	serve: require('./service/getPhotoService'),
        //	needLogin: true
        //},
        deleteUrlWord: {
            serve: require('./service/deleteUrlWordService'),
            needLogin: true
        },
        //deleteMusic: {
        //	serve: require('./service/deleteMusicService'),
        //	needLogin: true
        //},
        //uploadRecord: {
        //	serve: require('./service/uploadRecordService'),
        //},
        //updateLocation: {
        //	serve: require('./service/updateLocationService'),
        //},
        rss: {
            serve: require('./service/rssService'),
        },
        getCache: {
            serve: require('./service/getCacheService'),
        },
        getHtml: {
            serve: require('./service/getHtmlService'),
        },
        getTaobaoItem: {
            serve: require('./service/getTaobaoItemService1'),
        },
        getAdvLink: {
            serve: require('./service/getAdvLinkService1'),
            needCustomerLogin: config.domain == 'zoro.site'
        },
        getTaobaoLoginQrcode: {
            serve: require('./service/getTaobaoLoginQrcodeService'),
            needAdminLogin: config.domain == 'zoro.site'
        },
        // getTaobaoScreenshot: {
        //   serve: require('./service/getTaobaoScreenshotService'),
        // },
        getFanliCode: {
            serve: require('./service/getFanliCodeService1'),
        },
        submitFanliCode: {
            serve: require('./service/submitFanliCodeService1'),
        },
        customerLogin: {
            serve: require('./service/customerLoginService'),
        },
        getCode: {
            serve: require('./service/getCodeService'),
        },
        getCustomerLoginStatus: {
            serve: require('./service/getCustomerLoginStatusService'),
            needCustomerLogin: true
        },
        customerLogout: {
            serve: require('./service/customerLogoutService'),
        },
        getBill: {
            serve: require('./service/getBillService'),
            needCustomerLogin: true
        },
        setPassword: {
            serve: require('./service/setPasswordService'),
            needCustomerLogin: true
        },
        getAlipay: {
            serve: require('./service/getAlipayService'),
            needCustomerLogin: true
        },
        setAlipay: {
            serve: require('./service/setAlipayService'),
            needCustomerLogin: true
        },
        wechatPortal: {
            serve: require('./service/wechatPortalService')
        },
        wechatCardBatchget: {
            serve: require('./service/wechatCardBatchgetService')
        },
        wechatSnsJscode2session: {
            serve: require('./service/wechatSnsJscode2sessionService')
        },
        wechatTicketGetticket: {
            serve: require('./service/wechatTicketGetticketService')
        },
        getFyjTimestamp: {
            serve: require('./service/getFyjTimestampService')
        },
        wechatCardUserGetcardlist: {
            serve: require('./service/wechatCardUserGetcardlistService')
        },
        wechatAddCard: {
            serve: require('./service/wechatAddCardService')
        },
        wechatOpenCard: {
            serve: require('./service/wechatOpenCardService')
        },
        wechatCardGet: {
            serve: require('./service/wechatCardGetService')
        },
        getJdItem: {
            serve: require('./service/getJdItemService1'),
        },
        wechatCardCodeDecrypt: {
            serve: require('./service/wechatCardCodeDecryptService'),
        },
        fyjAddNote: {
            serve: require('./service/fyjAddNoteService'),
        },
        fyjGetNote: {
            serve: require('./service/fyjGetNoteService'),
        },
        //setBaiduPushChannelId: {
        //  serve: require('./service/setBaiduPushChannelIdService'),
        //  needCustomerLogin: true
        //},
        getBillData: {
            serve: require('./service/getBillDataService'),
            needAdminLogin: true
        },
        getLogData: {
            serve: require('./service/getLogDataService'),
            needAdminLogin: true
        },
        loginTaobao: {
            serve: require('./service/loginTaobaoService'),
            needAdminLogin: config.domain == 'zoro.site'
        },
        getCustomerBill: {
            serve: require('./service/getCustomerBillService'),
            needAdminLogin: true
        },
        getTaobaoBill: {
            serve: require('./service/getTaobaoBillService'),
            needAdminLogin: config.domain == 'zoro.site'
        },
        loginJd: {
            serve: require('./service/loginJdService'),
            needAdminLogin: config.domain == 'zoro.site'
        },
        register: {
            serve: require('./service/registerService'),
        },
        getCustomerLog: {
            serve: require('./service/getCustomerLogService'),
            needAdminLogin: true
        },
        //getWechatLoginQrcode: {
        //  serve: require('./service/getWechatLoginQrcodeService'),
        //  needAdminLogin: true
        //},
        getJdBill: {
            serve: require('./service/getJdBillService'),
            needAdminLogin: config.domain == 'zoro.site'
        },
        addChromeServer: {
            serve: require('./service/addChromeServerService')
        },
        getTop100Item: {
            serve: require('./service/getTop100ItemService')
        },
        getTaobaoCoupon: {
            serve: require('./service/getTaobaoCouponService')
        },
        claimBill: {
            serve: require('./service/claimBillService'),
            needCustomerLogin: true
        },
        wechatSnsOauth2AccessToken: {
            serve: require('./service/wechatSnsOauth2AccessTokenService')
        },
        getMoney: {
            serve: require('./service/getMoneyService'),
            needCustomerLogin: true
        },
        getPromoter: {
            serve: require('./service/getPromoterService'),
            needAdminLogin: true
        },
        setCustomer: {
            serve: require('./service/setCustomerService'),
            needAdminLogin: true
        },
        getCustomerForBill: {
            serve: require('./service/getCustomerForBillService'),
            needAdminLogin: true
        },
        setCustomerForBill: {
            serve: require('./service/setCustomerForBillService'),
            needAdminLogin: true
        },
        getActualLink: {
            serve: require('./service/getActualLinkService')
        },
        setReturnWay: {
            serve: require('./service/setReturnWayService'),
            needCustomerLogin: true
        },
        getPromoterPromotee: {
            serve: require('./service/getPromoterPromoteeService'),
            needAdminLogin: true
        },
        getPromotee: {
            serve: require('./service/getPromoteeService'),
            needCustomerLogin: true
        },
        getActivity0Data: {
            serve: require('./service/getActivity0DataService'),
            needCustomerLogin: true
        },
        getActivity0TotalData: {
            serve: require('./service/getActivity0TotalDataService'),
            needAdminLogin: true
        },
        handleBill: {
            serve: require('./service/handleBillService'),
            needAdminLogin: true
        },
        sendWechatRedPack: {
            serve: require('./service/sendWechatRedPackService'),
            needAdminLogin: true
        },
        getActivityList: {
            serve: require('./service/getActivityListService'),
            needAdminLogin: true
        },
        getActivityInfo: {
            serve: require('./service/getActivityInfoService'),
            needAdminLogin: true
        },
    }
if (config.domain == 'zoro.site') {
    global.pool = mysql.createPool({
        connectionLimit: 10,
        host: '123.56.115.107', //'139.129.45.92', //主机
        user: 'zoro', //MySQL认证用户名
        password: '<SB>buyaodenglu', //MySQL认证用户密码
        port: '3306', //端口号
        database: 'zoro'
    });
    require('./mng/mongoMng')
}

function serve(req, res) {
    sessionMng.get(req, res)
    var uri = req.url;
    if (uri.lastIndexOf('.do') != -1) {
        var svcn = uri.substring(uri.lastIndexOf('/') + 1, uri.lastIndexOf('.do')); // short for service name
        if (svc[svcn]) {
            if (svc[svcn].needLogin) {
                if (!req.session.user) {
                    res.statusCode = 200;
                    res.setHeader('Content-Type', 'text/json')
                    res.end(JSON.stringify({
                        result: 0
                    }))
                    return
                }
                if (svc[svcn].allowUsers && svc[svcn].allowUsers.indexOf(req.session.user.id) == -1) {
                    res.statusCode = 200;
                    res.setHeader('Content-Type', 'text/json')
                    res.end(JSON.stringify({
                        result: -1
                    }))
                    return
                }
            } else if (svc[svcn].needCustomerLogin) {
                if (!req.session.customer) {
                    res.statusCode = 200;
                    res.setHeader('Content-Type', 'text/json')
                    res.end(JSON.stringify({
                        result: 0
                    }))
                    return
                }
            } else if (svc[svcn].needAdminLogin) {
                if (!req.session.admin) {
                    res.statusCode = 200;
                    res.setHeader('Content-Type', 'text/json')
                    res.end(JSON.stringify({
                        result: 0
                    }))
                    return
                }
            }
            svc[svcn].serve(req, res);
            return
        } else {
            logger.warn('[' + __filename + ':' + __line + '] ' + svcn + '服务不存在')
        }
    }
    if (uri.lastIndexOf('.page') != -1) {
        var html_id = uri.substring(uri.lastIndexOf('/') + 1, uri.length - 5);
        htmlDao.select({
            html_id: html_id
        }, htmls => {
            if (htmls.length == 0) {
                res.writeHead(404, {
                    "Content-Type": "text/html"
                })
                res.end("<h1>404 Not Found</h1>")
            } else {
                fs.readFile(__dirname + '/../dist/index.html', 'utf-8', (err, data) => {
                    if (err) {
                        logger.error('[' + __filename + ':' + __line + ']', err)
                        res.writeHead(404, {
                            "Content-Type": "text/html"
                        })
                        res.end("<h1>404 Not Found</h1>")
                        return
                    }
                    res.writeHead(200, {
                        'Content-Type': 'text/html'
                    })
                    res.end(data)
                })
            }
        })
        return
    }
    // if (uri.lastIndexOf('.cache') != -1) {
    //     var cacheId = uri.substring(uri.lastIndexOf('/') + 1, uri.length - 6);
    //     require('./dao/cacheDao').select({
    //         id: cacheId
    //     }, caches => {
    //         res.writeHead(200, {
    //             'Content-Type': 'text/html'
    //         })
    //         res.end(caches[0].html)
    //     })
    //     return
    // }
    // if (uri.indexOf('/fyj') == 0) {//范勇军
    //   var _req = http.request({
    //     host: '127.0.0.1',
    //     path: uri.substring(4),
    //     method: req.method // 请求方式
    //   }, function (_res) {
    //     _res.pipe(res);
    //     _res.on('end', function () {
    //     });
    //   });
    //   if (/POST|PUT/i.test(req.method)) {
    //     req.pipe(_req);
    //   } else {
    //     _req.end();
    //   }
    //   return
    // }
    var pathname = __dirname + '/../'
    if (uri.lastIndexOf('.m3u8') != -1 || uri.lastIndexOf('.ts') != -1) {
        pathname += 'm3u8'
    } else {
        pathname += 'dist'
        if (req.headers.host == 'coupon.etourly.com')
            pathname += '/coupon'
    }
    try {
        pathname += decodeURIComponent(url.parse(uri).pathname);
    } catch (err) {
        logger.error('[' + __filename + ':' + __line + ']', err, uri)
        res.writeHead(404, {
            'Content-Type': 'text/html'
        })
        res.end('<h1>404 Not Found</h1>')
        return
    }
    if (path.extname(pathname) == '') {
        pathname += "/";
    }
    if (pathname.charAt(pathname.length - 1) == "/") {
        pathname += 'index.html';
    }
    fs.exists(pathname, (exists) => {
        if (exists) {
            switch (path.extname(pathname).toLowerCase()) {
                case '.html':
                    res.writeHead(200, {
                        'Content-Type': 'text/html'
                    });
                    break;
                case '.js':
                    res.writeHead(200, {
                        'Content-Type': 'text/javascript'
                    });
                    break;
                case '.css':
                    res.writeHead(200, {
                        'Content-Type': 'text/css'
                    });
                    break;
                case '.gif':
                    res.writeHead(200, {
                        'Content-Type': 'image/gif'
                    });
                    break;
                case '.jpg':
                    res.writeHead(200, {
                        'Content-Type': 'image/jpeg'
                    });
                    break;
                case '.png':
                    res.writeHead(200, {
                        'Content-Type': 'image/png'
                    });
                    break;
                case '.mp3':
                    res.writeHead(200, {
                        'Content-Type': 'video/mp3'
                    });
                    break;
                case '.mp4':
                    res.writeHead(200, {
                        'Content-Type': 'video/mp4'
                    });
                    break;
                default:
                    res.writeHead(200, {
                        'Content-Type': 'application/octet-stream'
                    });
            }
            if (path.extname(pathname).toLowerCase() == '.jpg' && url.parse(uri).query) {
                var reqObj = {}
                url.parse(uri).query.split('&').forEach(kv => {
                    reqObj[kv.split('=')[0]] = kv.split('=')[1]
                })
                if (reqObj.width) {
                    res.end(require('images')(pathname).size(400).encode('jpg', {
                        quality: 50
                    }))
                    return
                }
            }
            if (path.extname(pathname).toLowerCase() == '.mp4' && url.parse(uri).query) {
                var reqObj = {}
                url.parse(uri).query.split('&').forEach(kv => {
                    reqObj[kv.split('=')[0]] = kv.split('=')[1]
                })
                if (reqObj.width) {
                    var tmpPathname = '/tmp/' + pathname.substring(pathname.lastIndexOf('/') + 1) + reqObj.width
                    if (!fs.existsSync(tmpPathname)) {
                        new ffmpeg(pathname).size(reqObj.width + 'x?')
                            .fps(10)
                            .audioBitrate('32k')
                            .format('mp4')
                            .on('end', function() {
                                var rs = fs.createReadStream(tmpPathname);
                                rs.on('end', () => {
                                    res.end()
                                })
                                rs.pipe(res)
                            })
                            .on('error', function(err) {
                                logger.error('[' + __filename + ':' + __line + ']', 'an error happened: ', err)
                            }).save(tmpPathname)
                        return
                    }
                    pathname = tmpPathname
                }
            }
            var rs = fs.createReadStream(pathname);
            rs.on('end', () => {
                res.end()
            })
            rs.pipe(res)
            return
        }
        // logger.debug('[' + __filename + ':' + __line + ']', uri, pathname, '不存在')
        res.writeHead(404, {
            'Content-Type': 'text/html'
        })
        res.end('<h1>404 Not Found</h1>')
    })
}

var httpPort = config.domain == '' ? 9080 : 80
const httpServer = http.createServer(serve);
httpServer.listen(httpPort, () => {
    logger.debug('[' + __filename + ':' + __line + ']', 'http listening ' + httpPort)
})

if (config.domain == '') {
    var httpsPort = config.domain == '' ? 8443 : 443
    var options = {
        key: fs.readFileSync(config.domain == '' ? './server.key' : '/etc/letsencrypt/live/' + config.domain + '/privkey.pem'),
        cert: fs.readFileSync(config.domain == '' ? './server.crt' : '/etc/letsencrypt/live/' + config.domain + '/cert.pem'),
        // ciphers: ['TLS_RSA_WITH_AES_128_CBC_SHA256',
        //   'TLS_RSA_WITH_AES_128_CBC_SHA',
        //   'TLS_RSA_WITH_AES_256_CBC_SHA256',
        //   'TLS_RSA_WITH_AES_256_CBC_SHA',
        //   'SSL_RSA_WITH_3DES_EDE_CBC_SHA',
        //   'ECDHE-RSA-AES128-GCM-SHA256:',
        //   'ECDHE-ECDSA-AES128-GCM-SHA256:',
        //   'ECDHE-RSA-AES256-GCM-SHA384:',
        //   'ECDHE-ECDSA-AES256-GCM-SHA384:',
        //   'DHE-RSA-AES128-GCM-SHA256:',
        //   'ECDHE-RSA-AES128-SHA256:',
        //   'DHE-RSA-AES128-SHA256:',
        //   'ECDHE-RSA-AES256-SHA384:',
        //   'DHE-RSA-AES256-SHA384:',
        //   'ECDHE-RSA-AES256-SHA256:',
        //   'DHE-RSA-AES256-SHA256:',
        //   'HIGH:',
        //   '!aNULL:',
        //   '!eNULL:',
        //   '!EXPORT:',
        //   '!DES:',
        //   '!RC4:',
        //   '!MD5:',
        //   '!PSK:',
        //   '!SRP:',
        //   '!CAMELLIA'].join(':'),
        // secureProtocol: 'TLSv1_2_method'
    }
    const httpsServer = https.createServer(options, serve);
    httpsServer.on('close', () => {}).listen(httpsPort, () => {
        logger.debug('[' + __filename + ':' + __line + ']https listening ' + httpsPort)
    })
}

/*new WebSocketServer({
server: httpServer
}).on('connection', ws => {
sessionMng.get(ws.upgradeReq)
if (!ws.upgradeReq.session.user)
return
ws.upgradeReq.session.webSocket = ws
ws.on('message', msg => {
var svcn = msg.split(' ')[0]// short for service name
switch (svcn) {
case 'delLog':
require('./mng/logMng').del(msg.substring(svcn.length + 1))
break
}
}).on('close', () => {
delete ws.upgradeReq.session.webSocket
})
ws.send('log ' + JSON.stringify(require('./mng/logMng').get()));
})*/

if (config.domain == 'zoro.site') {
    setInterval(() => require('./task/deleteDuplicateUrlTask').start(), 120 * 1000)
        // setInterval(() => require('./task/cgsTask').start(), 120000)
    setInterval(() => require('./task/updatePTask').start(), 120 * 1000)
        // require('./getHtmlWithChrome')
        //setInterval(() => require('./task/crawlTask').start(), 120000)
    setInterval(() => require('./task/getTaobaoBillTask1').start(), 3 * 3600 * 1000)
    setInterval(() => require('./task/handleBillTask').start(), 1800 * 1000)
        // setInterval(() => require('./task/getTaobaoAdvLinkTask').start(), 60000)
    setInterval(() => require('./task/getJdBillTask').start(), 1200 * 1000)
    setInterval(() => require('./task/jumpToTaobaoIndexTask').start(), 50 * 60 * 1000)
    require('./util/Proxy').startProxyServer({
        exPort: 8080,
        inPort: 18080
    })
    require('./util/Proxy').startProxyServer({
        exPort: 8081,
        inPort: 18081
    })
    require('./util/Proxy').startProxyServer({
        exPort: 8082,
        inPort: 18082
    })
}

if (config.domain == '') {
    require('./util/Proxy').startProxyClient({
        priority: config.local.proxyClientPriority,
        port: config.local.proxyClientPort
    })
    setInterval(() => require('./task/addChromeServerTask').start(config.local.chromeServerPriority), 60 * 1000)
}

process.on('unhandledRejection', (reason, promise) => {
    logger.error('[' + __filename + ':' + __line + ']', reason)
})
process.on('uncaughtException', (err) => {
    logger.error('[' + __filename + ':' + __line + ']', err)
})